#ifndef COMMONLISTENER_H
#define COMMONLISTENER_H

#include <map>
#include <list>
#include <functional>
#include <stdint.h>
#include <string>
#include <boost/function.hpp>
#include <boost/asio.hpp>
#include <TcpServer.h>

#define MSG_HEAD 0xFAFAFBFB
#define MSG_HEAD_POS 0
#define MSG_LENTH_POS 4 //the lenth included the header and lenth size itself
#define MSG_RESERVED_POS 8
#define MSG_TYPE_ID_POS 12
#define MSG_TYPE_POS 12
#define MSG_ID_POS 14
#define MSG_DATA_COUNT 16
#define MSG_MINIMAL 20
#define MSG_DATA_POS 20

inline unsigned long getMsgTypeID(const std::string & msg){
	return msg.length() >=MSG_MINIMAL ? (*(unsigned long*)msg.c_str()+MSG_TYPE_POS) : 0;
}

std::map<string, string> decodeMsgData(const std::string & msg){
	if (msg.length() >MSG_MINIMAL){
		const char* md = msg.c_str();
		size_t len = *(unsigned long*)md+MSG_LENTH_POS;
		size_t count = *(size_t*)md+MSG_DATA_COUNT;
		const char* pos_ptr = md + MSG_DATA_POS;
		unsigned short keylen = 0;
		unsigned short vallen = 0;
		std::map<string, string> data;
		std::string key;
		std::string value;
		for (size_t i =0 ;i <count; ++i){
			keylen = *(unsigned short*)pos_ptr;
			pos_ptr += sizeof ( unsigned short);
			key = std::string( pos_ptr, pos_ptr+keylen);
			pos_ptr += keylen;
			vallen = *(unsigned short*)pos_ptr;
			pos_ptr += sizeof ( unsigned short);
			value = std::string( pos_ptr, pos_ptr+vallen);
			pos_ptr += vallen;
			data[key] = value;
		}
		if ( pos_ptr != md+len){
			std::cout<<"*** decodeMsgData: something wrong!"<<std::endl;
		}
		return data;
	}else{
		return std::map<string, string>();
	}
}
std::string encodeMsgData(const std::map<string, string> & data, unsigned short msgtype, unsigned short msgid){
	char msg[4096];
	char * msg_pos = msg + MSG_DATA_POS;
	char * msg_end = msg + 4096;
	memset( msg +MSG_HEAD_POS, MSG_HEAD, sizeof(unsigned long));
	memset( msg +MSG_DATA_COUNT, data.size(), sizeof(unsigned long));
	memset( msg +MSG_TYPE_POS, msgtype, sizeof(unsigned short));
	memset( msg +MSG_ID_POS, msgid, sizeof(unsigned short));
	for ( std::map<string, string>::const_iterator it = data.begin(); it != data.end() ; ++it){
		memset( msg_pos, it->first.length(), sizeof(unsigned short) );
		msg_pos+=sizeof(unsigned short);
		memcpy( msg_pos, it->first.c_str(),  it->first.length());
		msg_pos+=it->first.length();
		if ( msg_pos > msg_end ){
			std::cout<<"*** encodeMsgData: something wrong!"<<std::endl;
		}
	}
	return std::string(msg, msg_pos);
}

using namespace std;

class CommonListener{
    struct Impl;
    Impl *impl_;

    CommonListener();
    ~CommonListener();
	static  CommonListener* inst;
public:

	static CommonListener *instance();

	bool dispatch( ClientHost*, const std::string &);
	HostCallback getCallback();
};




#endif // COMMONLISTENER_H
